package cn.edu.wfit.modules.directionmanagement.service.impl;

import cn.edu.wfit.modules.directionmanagement.config.OnlineIdeConfig;
import cn.edu.wfit.modules.directionmanagement.domain.CodeExecutionRequest;
import cn.edu.wfit.modules.directionmanagement.domain.CodeExecutionResponse;
import cn.edu.wfit.modules.directionmanagement.service.OnlineIdeService;
import cn.edu.wfit.modules.directionmanagement.util.CodeExecutionUtil;
import cn.edu.wfit.modules.directionmanagement.util.CodeSecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;

/**
 * 在线IDE服务实现类
 */
@Service
public class OnlineIdeServiceImpl implements OnlineIdeService {

    @Autowired
    private OnlineIdeConfig onlineIdeConfig;

    @Override
    public CodeExecutionResponse executeCode(CodeExecutionRequest request) {
        CodeExecutionResponse response = new CodeExecutionResponse();
        String language = request.getLanguage().toLowerCase();
        String sourceCode = request.getSourceCode();
        String input = request.getInput();

        // 安全检查
        if (!isCodeSafe(language, sourceCode)) {
            response.setSuccess(false);
            response.setError("代码包含危险操作，执行被拒绝");
            return response;
        }

        long startTime = System.currentTimeMillis();

        try {
            // 根据语言类型执行相应代码
            switch (language) {
                case "java":
                    executeJavaCode(sourceCode, input, response);
                    break;
                case "python":
                    executePythonCode(sourceCode, input, response);
                    break;
                case "cpp":
                    executeCppCode(sourceCode, input, response);
                    break;
                default:
                    response.setSuccess(false);
                    response.setError("不支持的编程语言: " + language);
                    return response;
            }

            response.setSuccess(true);
        } catch (Exception e) {
            response.setSuccess(false);
            response.setError("代码执行出错: " + e.getMessage());
        } finally {
            long endTime = System.currentTimeMillis();
            response.setExecutionTime(endTime - startTime);
        }

        return response;
    }

    /**
     * 执行Java代码
     */
    private void executeJavaCode(String sourceCode, String input, CodeExecutionResponse response) throws Exception {
        // 创建临时目录
        String tempDir = CodeExecutionUtil.createTempDirectory();
        try {
            // 写入源代码文件
            String fileName = "Main.java";
            String filePath = tempDir + File.separator + fileName;
            CodeExecutionUtil.writeToFile(filePath, sourceCode);

            // 编译Java代码
            CodeExecutionUtil.ProcessResult compileResult = CodeExecutionUtil.executeCommand(
                    new String[]{"javac", fileName},
                    new File(tempDir),
                    null,
                    onlineIdeConfig
            );

            if (!compileResult.isSuccess()) {
                response.setError("编译失败: " + compileResult.getError());
                return;
            }

            if (!compileResult.getError().isEmpty()) {
                response.setError("编译警告: " + compileResult.getError());
            }

            // 执行编译后的Java程序，指定编码为GBK以确保中文正确显示
            CodeExecutionUtil.ProcessResult executeResult = CodeExecutionUtil.executeCommand(
                    new String[]{"java", "-Dfile.encoding=GBK", "-Dsun.jnu.encoding=GBK", "Main"},
                    new File(tempDir),
                    input,
                    onlineIdeConfig
            );

            if (!executeResult.isSuccess()) {
                response.setError("执行失败: " + executeResult.getError());
                return;
            }

            response.setOutput(executeResult.getOutput());
            if (!executeResult.getError().isEmpty()) {
                response.setError(executeResult.getError());
            }
        } finally {
            // 清理临时目录
            CodeExecutionUtil.deleteDirectory(new File(tempDir));
        }
    }

    /**
     * 执行Python代码
     */
    private void executePythonCode(String sourceCode, String input, CodeExecutionResponse response) throws Exception {
        // 创建临时目录
        String tempDir = CodeExecutionUtil.createTempDirectory();
        try {
            // 写入源代码文件
            String fileName = "script.py";
            String filePath = tempDir + File.separator + fileName;
            
            // 检查源代码是否包含编码声明，如果没有则添加
            String processedSourceCode = sourceCode;
            if (!sourceCode.contains("coding") && !sourceCode.contains("encoding")) {
                // Python文件统一使用UTF-8编码声明
                processedSourceCode = "# -*- coding: utf-8 -*-\n" + sourceCode;
            }
            
            CodeExecutionUtil.writeToFile(filePath, processedSourceCode);

            // 执行Python代码
            CodeExecutionUtil.ProcessResult executeResult = CodeExecutionUtil.executeCommand(
                    new String[]{"python", fileName},
                    new File(tempDir),
                    input,
                    onlineIdeConfig,
                    true  // 标记为Python执行，使用特殊编码处理
            );

            if (!executeResult.isSuccess()) {
                response.setError("执行失败: " + executeResult.getError());
                return;
            }

            response.setOutput(executeResult.getOutput());
            if (!executeResult.getError().isEmpty()) {
                response.setError(executeResult.getError());
            }
        } finally {
            // 清理临时目录
            CodeExecutionUtil.deleteDirectory(new File(tempDir));
        }
    }

    /**
     * 执行C++代码
     */
    private void executeCppCode(String sourceCode, String input, CodeExecutionResponse response) throws Exception {
        // 创建临时目录
        String tempDir = CodeExecutionUtil.createTempDirectory();
        try {
            // 写入源代码文件
            String fileName = "program.cpp";
            String filePath = tempDir + File.separator + fileName;
            CodeExecutionUtil.writeToFile(filePath, sourceCode);

            // 根据操作系统确定可执行文件名称
            String executableName = System.getProperty("os.name").toLowerCase().contains("win") ? "program.exe" : "program";
            
            // 编译C++代码
            CodeExecutionUtil.ProcessResult compileResult = CodeExecutionUtil.executeCommand(
                    new String[]{"g++", fileName, "-o", executableName},
                    new File(tempDir),
                    null,
                    onlineIdeConfig
            );

            if (!compileResult.isSuccess()) {
                response.setError("编译失败: " + compileResult.getError());
                return;
            }

            if (!compileResult.getError().isEmpty()) {
                response.setError("编译警告: " + compileResult.getError());
            }

            // 检查可执行文件是否生成
            File executableFile = new File(tempDir, executableName);
            if (!executableFile.exists()) {
                response.setError("编译失败: 未生成可执行文件 " + executableName);
                return;
            }

            // 在Windows上直接执行程序，在Unix/Linux上直接执行
            String[] executeCommand;
            if (System.getProperty("os.name").toLowerCase().contains("win")) {
                // Windows系统使用完整路径执行，不需要cmd /c
                executeCommand = new String[]{executableFile.getAbsolutePath()};
            } else {
                // Unix/Linux系统使用相对路径执行
                executeCommand = new String[]{"./" + executableName};
            }
            
            // 执行编译后的程序
            CodeExecutionUtil.ProcessResult executeResult = CodeExecutionUtil.executeCommand(
                    executeCommand,
                    new File(tempDir),
                    input,
                    onlineIdeConfig
            );

            if (!executeResult.isSuccess()) {
                response.setError("执行失败: " + executeResult.getError());
                return;
            }

            response.setOutput(executeResult.getOutput());
            if (!executeResult.getError().isEmpty()) {
                response.setError(executeResult.getError());
            }
        } finally {
            // 清理临时目录
            CodeExecutionUtil.deleteDirectory(new File(tempDir));
        }
    }

    /**
     * 检查代码是否安全
     * @param language 编程语言
     * @param sourceCode 源代码
     * @return 是否安全
     */
    private boolean isCodeSafe(String language, String sourceCode) {
        switch (language) {
            case "java":
                return CodeSecurityUtil.isJavaCodeSafe(sourceCode);
            case "python":
                return CodeSecurityUtil.isPythonCodeSafe(sourceCode);
            case "cpp":
                return CodeSecurityUtil.isCppCodeSafe(sourceCode);
            default:
                return false;
        }
    }
}